// Copyright 2021 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.

#include "clay/ui/event/key_code_converter.h"

#include <sstream>
#include <unordered_map>

#include "clay/ui/event/key_codes.h"

namespace clay {

using namespace keycodes;  // NOLINT

namespace {  // anonymous namespace to force internal linkage

const std::unordered_map<uint64_t, const char*> logical_key2web_key = {
    // translate from kWebToLogicalKey
    {0x00100000d08, "AVRInput"},
    {0x00100000d09, "AVRPower"},
    {0x00100000101, "Accel"},
    {0x00100000501, "Accept"},
    {0x00100000502, "Again"},
    {0x00100000701, "AllCandidates"},
    {0x00100000702, "Alphanumeric"},
    {0x00100000103, "AltGraph"},
    {0x00100001001, "AppSwitch"},
    {0x00100000301, "ArrowDown"},
    {0x00100000302, "ArrowLeft"},
    {0x00100000303, "ArrowRight"},
    {0x00100000304, "ArrowUp"},
    {0x00100000503, "Attn"},
    {0x00100000d01, "AudioBalanceLeft"},
    {0x00100000d02, "AudioBalanceRight"},
    {0x00100000d03, "AudioBassBoostDown"},
    {0x00100000e02, "AudioBassBoostToggle"},
    {0x00100000d04, "AudioBassBoostUp"},
    {0x00100000d05, "AudioFaderFront"},
    {0x00100000d06, "AudioFaderRear"},
    {0x00100000d07, "AudioSurroundModeNext"},
    {0x00100000e04, "AudioTrebleDown"},
    {0x00100000e05, "AudioTrebleUp"},
    {0x00100000a0f, "AudioVolumeDown"},
    {0x00100000a11, "AudioVolumeMute"},
    {0x00100000a10, "AudioVolumeUp"},
    {0x00100000008, "Backspace"},
    {0x00100000601, "BrightnessDown"},
    {0x00100000602, "BrightnessUp"},
    {0x00100000c01, "BrowserBack"},
    {0x00100000c02, "BrowserFavorites"},
    {0x00100000c03, "BrowserForward"},
    {0x00100000c04, "BrowserHome"},
    {0x00100000c05, "BrowserRefresh"},
    {0x00100000c06, "BrowserSearch"},
    {0x00100000c07, "BrowserStop"},
    {0x00100001002, "Call"},
    {0x00100000603, "Camera"},
    {0x00100001003, "CameraFocus"},
    {0x00100000504, "Cancel"},
    {0x00100000104, "CapsLock"},
    {0x00100000d0a, "ChannelDown"},
    {0x00100000d0b, "ChannelUp"},
    {0x00100000401, "Clear"},
    {0x00100000a01, "Close"},
    {0x00100000d12, "ClosedCaptionToggle"},
    {0x00100000703, "CodeInput"},
    {0x00100000d0c, "ColorF0Red"},
    {0x00100000d0d, "ColorF1Green"},
    {0x00100000d0e, "ColorF2Yellow"},
    {0x00100000d0f, "ColorF3Blue"},
    {0x00100000d10, "ColorF4Grey"},
    {0x00100000d11, "ColorF5Brown"},
    {0x00100000704, "Compose"},
    {0x00100000505, "ContextMenu"},
    {0x00100000705, "Convert"},
    {0x00100000402, "Copy"},
    {0x00100000403, "CrSel"},
    {0x00100000404, "Cut"},
    {0x00100000d4f, "DVR"},
    {0x0010000007f, "Delete"},
    {0x00100000d13, "Dimmer"},
    {0x00100000d14, "DisplaySwap"},
    {0x00100000714, "Eisu"},
    {0x00100000604, "Eject"},
    {0x00100000305, "End"},
    {0x00100001004, "EndCall"},
    {0x0010000000d, "Enter"},
    {0x00100000405, "EraseEof"},
    {0x0010000001b, "Escape"},
    {0x00100000406, "ExSel"},
    {0x00100000506, "Execute"},
    {0x00100000d15, "Exit"},
    {0x00100000801, "F1"},
    {0x0010000080a, "F10"},
    {0x0010000080b, "F11"},
    {0x0010000080c, "F12"},
    {0x0010000080d, "F13"},
    {0x0010000080e, "F14"},
    {0x0010000080f, "F15"},
    {0x00100000810, "F16"},
    {0x00100000811, "F17"},
    {0x00100000812, "F18"},
    {0x00100000813, "F19"},
    {0x00100000802, "F2"},
    {0x00100000814, "F20"},
    {0x00100000815, "F21"},
    {0x00100000816, "F22"},
    {0x00100000817, "F23"},
    {0x00100000818, "F24"},
    {0x00100000803, "F3"},
    {0x00100000804, "F4"},
    {0x00100000805, "F5"},
    {0x00100000806, "F6"},
    {0x00100000807, "F7"},
    {0x00100000808, "F8"},
    {0x00100000809, "F9"},
    {0x00100000d16, "FavoriteClear0"},
    {0x00100000d17, "FavoriteClear1"},
    {0x00100000d18, "FavoriteClear2"},
    {0x00100000d19, "FavoriteClear3"},
    {0x00100000d1a, "FavoriteRecall0"},
    {0x00100000d1b, "FavoriteRecall1"},
    {0x00100000d1c, "FavoriteRecall2"},
    {0x00100000d1d, "FavoriteRecall3"},
    {0x00100000d1e, "FavoriteStore0"},
    {0x00100000d1f, "FavoriteStore1"},
    {0x00100000d20, "FavoriteStore2"},
    {0x00100000d21, "FavoriteStore3"},
    {0x00100000706, "FinalMode"},
    {0x00100000507, "Find"},
    {0x00100000106, "Fn"},
    {0x00100000107, "FnLock"},
    {0x00100001005, "GoBack"},
    {0x00100001006, "GoHome"},
    {0x00100000707, "GroupFirst"},
    {0x00100000708, "GroupLast"},
    {0x00100000709, "GroupNext"},
    {0x0010000070a, "GroupPrevious"},
    {0x00100000d22, "Guide"},
    {0x00100000d23, "GuideNextDay"},
    {0x00100000d24, "GuidePreviousDay"},
    {0x00100000711, "HangulMode"},
    {0x00100000712, "HanjaMode"},
    {0x00100000715, "Hankaku"},
    {0x00100001007, "HeadsetHook"},
    {0x00100000508, "Help"},
    {0x00100000609, "Hibernate"},
    {0x00100000716, "Hiragana"},
    {0x00100000717, "HiraganaKatakana"},
    {0x00100000306, "Home"},
    {0x00100000108, "Hyper"},
    {0x00100000d25, "Info"},
    {0x00100000407, "Insert"},
    {0x00100000d26, "InstantReplay"},
    {0x00100000713, "JunjaMode"},
    {0x00100000718, "KanaMode"},
    {0x00100000719, "KanjiMode"},
    {0x0010000071a, "Katakana"},
    {0x00100001201, "Key11"},
    {0x00100001202, "Key12"},
    {0x00100001008, "LastNumberRedial"},
    {0x00100000b06, "LaunchApplication1"},
    {0x00100000b01, "LaunchApplication2"},
    {0x00100000b0e, "LaunchAssistant"},
    {0x00100000b02, "LaunchCalendar"},
    {0x00100000b0c, "LaunchContacts"},
    {0x00100000b0f, "LaunchControlPanel"},
    {0x00100000b03, "LaunchMail"},
    {0x00100000b04, "LaunchMediaPlayer"},
    {0x00100000b05, "LaunchMusicPlayer"},
    {0x00100000b0d, "LaunchPhone"},
    {0x00100000b07, "LaunchScreenSaver"},
    {0x00100000b08, "LaunchSpreadsheet"},
    {0x00100000b09, "LaunchWebBrowser"},
    {0x00100000b0a, "LaunchWebCam"},
    {0x00100000b0b, "LaunchWordProcessor"},
    {0x00100000d27, "Link"},
    {0x00100000d28, "ListProgram"},
    {0x00100000d29, "LiveContent"},
    {0x00100000d2a, "Lock"},
    {0x00100000605, "LogOff"},
    {0x00100000a02, "MailForward"},
    {0x00100000a03, "MailReply"},
    {0x00100000a04, "MailSend"},
    {0x0010000100a, "MannerMode"},
    {0x00100000d2b, "MediaApps"},
    {0x00100000d50, "MediaAudioTrack"},
    {0x00100000d5b, "MediaClose"},
    {0x00100000d2c, "MediaFastForward"},
    {0x00100000d2d, "MediaLast"},
    {0x00100000d2e, "MediaPause"},
    {0x00100000d2f, "MediaPlay"},
    {0x00100000a05, "MediaPlayPause"},
    {0x00100000d30, "MediaRecord"},
    {0x00100000d31, "MediaRewind"},
    {0x00100000d32, "MediaSkip"},
    {0x00100000d51, "MediaSkipBackward"},
    {0x00100000d52, "MediaSkipForward"},
    {0x00100000d53, "MediaStepBackward"},
    {0x00100000d54, "MediaStepForward"},
    {0x00100000a07, "MediaStop"},
    {0x00100000d55, "MediaTopMenu"},
    {0x00100000a08, "MediaTrackNext"},
    {0x00100000a09, "MediaTrackPrevious"},
    {0x00100000e06, "MicrophoneToggle"},
    {0x00100000e07, "MicrophoneVolumeDown"},
    {0x00100000e09, "MicrophoneVolumeMute"},
    {0x00100000e08, "MicrophoneVolumeUp"},
    {0x0010000070b, "ModeChange"},
    {0x00100000d56, "NavigateIn"},
    {0x00100000d57, "NavigateNext"},
    {0x00100000d58, "NavigateOut"},
    {0x00100000d59, "NavigatePrevious"},
    {0x00100000a0a, "New"},
    {0x0010000070c, "NextCandidate"},
    {0x00100000d33, "NextFavoriteChannel"},
    {0x00100000d34, "NextUserProfile"},
    {0x0010000070d, "NonConvert"},
    {0x00100001009, "Notification"},
    {0x0010000010a, "NumLock"},
    {0x00100000d35, "OnDemand"},
    {0x00100000a0b, "Open"},
    {0x00100000307, "PageDown"},
    {0x00100000308, "PageUp"},
    {0x00100000d5a, "Pairing"},
    {0x00100000408, "Paste"},
    {0x00100000509, "Pause"},
    {0x00100000d36, "PinPDown"},
    {0x00100000d37, "PinPMove"},
    {0x00100000d38, "PinPToggle"},
    {0x00100000d39, "PinPUp"},
    {0x0010000050a, "Play"},
    {0x00100000d3a, "PlaySpeedDown"},
    {0x00100000d3b, "PlaySpeedReset"},
    {0x00100000d3c, "PlaySpeedUp"},
    {0x00100000606, "Power"},
    {0x00100000607, "PowerOff"},
    {0x0010000070e, "PreviousCandidate"},
    {0x00100000a0c, "Print"},
    {0x00100000608, "PrintScreen"},
    {0x0010000070f, "Process"},
    {0x0010000050b, "Props"},
    {0x00100000d3d, "RandomToggle"},
    {0x00100000d3e, "RcLowBattery"},
    {0x00100000d3f, "RecordSpeedNext"},
    {0x00100000409, "Redo"},
    {0x00100000d40, "RfBypass"},
    {0x0010000071b, "Romaji"},
    {0x00100000d45, "STBInput"},
    {0x00100000d46, "STBPower"},
    {0x00100000a0d, "Save"},
    {0x00100000d41, "ScanChannelsToggle"},
    {0x00100000d42, "ScreenModeNext"},
    {0x0010000010c, "ScrollLock"},
    {0x0010000050c, "Select"},
    {0x00100000d43, "Settings"},
    {0x00100000111, "ShiftLevel5"},
    {0x00100000710, "SingleCandidate"},
    {0x00100000901, "Soft1"},
    {0x00100000902, "Soft2"},
    {0x00100000903, "Soft3"},
    {0x00100000904, "Soft4"},
    {0x00100000905, "Soft5"},
    {0x00100000906, "Soft6"},
    {0x00100000907, "Soft7"},
    {0x00100000908, "Soft8"},
    {0x00100000f01, "SpeechCorrectionList"},
    {0x00100000f02, "SpeechInputToggle"},
    {0x00100000a0e, "SpellCheck"},
    {0x00100000d44, "SplitScreenToggle"},
    {0x0010000060a, "Standby"},
    {0x00100000d47, "Subtitle"},
    {0x0010000010e, "Super"},
    {0x0010000010f, "Symbol"},
    {0x00100000110, "SymbolLock"},
    {0x00100000d49, "TV"},
    {0x00100001101, "TV3DMode"},
    {0x00100001102, "TVAntennaCable"},
    {0x00100001103, "TVAudioDescription"},
    {0x00100001104, "TVAudioDescriptionMixDown"},
    {0x00100001105, "TVAudioDescriptionMixUp"},
    {0x00100001106, "TVContentsMenu"},
    {0x00100001107, "TVDataService"},
    {0x00100000d4a, "TVInput"},
    {0x00100001108, "TVInputComponent1"},
    {0x00100001109, "TVInputComponent2"},
    {0x0010000110a, "TVInputComposite1"},
    {0x0010000110b, "TVInputComposite2"},
    {0x0010000110c, "TVInputHDMI1"},
    {0x0010000110d, "TVInputHDMI2"},
    {0x0010000110e, "TVInputHDMI3"},
    {0x0010000110f, "TVInputHDMI4"},
    {0x00100001110, "TVInputVGA1"},
    {0x00100001111, "TVMediaContext"},
    {0x00100001112, "TVNetwork"},
    {0x00100001113, "TVNumberEntry"},
    {0x00100000d4b, "TVPower"},
    {0x00100001114, "TVRadioService"},
    {0x00100001115, "TVSatellite"},
    {0x00100001116, "TVSatelliteBS"},
    {0x00100001117, "TVSatelliteCS"},
    {0x00100001118, "TVSatelliteToggle"},
    {0x00100001119, "TVTerrestrialAnalog"},
    {0x0010000111a, "TVTerrestrialDigital"},
    {0x0010000111b, "TVTimer"},
    {0x00100000009, "Tab"},
    {0x00100000d48, "Teletext"},
    {0x0010000040a, "Undo"},
    {0x00100000001, "Unidentified"},
    {0x00100000d4c, "VideoModeNext"},
    {0x0010000100b, "VoiceDial"},
    {0x0010000060b, "WakeUp"},
    {0x00100000d4d, "Wink"},
    {0x0010000071c, "Zenkaku"},
    {0x0010000071d, "ZenkakuHankaku"},
    {0x0010000050d, "ZoomIn"},
    {0x0010000050e, "ZoomOut"},
    {0x00100000d4e, "ZoomToggle"},

    // translate from kWebLogicalLocationMap
    {kLogicalShiftLeft, "Shift"},
    {kLogicalShiftRight, "Shift"},
    {kLogicalAltLeft, "Alt"},
    {kLogicalAltRight, "Alt"},
    {kLogicalControlLeft, "Control"},
    {kLogicalControlRight, "Control"},
    {kLogicalMetaLeft, "Meta"},
    {kLogicalMetaRight, "Meta"},
};

}  // namespace

std::string KeyCodeConverter::ConvertToWebKey(LogicalKeyboardKey key_code,
                                              const std::string& character) {
  uint64_t logical = static_cast<uint64_t>(key_code);
  auto iter = logical_key2web_key.find(logical);
  if (iter != logical_key2web_key.end()) {  // key map
    return iter->second;
  } else if (!character.empty()) {  // visual characters
    return character;
  } else if (logical <= 0xFF) {  // visual characters
    return std::string(1, logical);
  } else {  // fallback, return logical key in hexadecimal form
    std::stringstream ss;
    ss << std::hex << "0x" << logical;
    return ss.str();
  }
}

}  // namespace clay
